package design.pattern.Lu15CompositePattern;

import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.*;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import static design.pattern.Lu15CompositePattern.CompositePattern06.TreeNodeLink.Operator.NOT_EQ;

/**
 * @program JavaBase
 * @description: 组合模式&责任链模式 - 决策树
 * @author: zhanglu
 * @create: 2022-05-16 15:14:00
 */
@Slf4j
public class CompositePattern06 {

    /********************规则树数据模型********************/

    //规则树-聚合-整棵树
    @Data
    static class TreeRich{
        private TreeRoot treeRoot;                  //树根信息
        private Map<String, TreeNode> treeNodeMap;    //树节点ID -> 子节点
    }

    //决策结果
    @Data
    @Builder
    @Accessors(chain = true)
    @AllArgsConstructor
    @NoArgsConstructor
    static class EngineResult{
        private String treeId;        //规则树ID
        private String nodeId;        //果实节点ID
        private Integer nodeValue;   //果实节点值
    }

    //规则树根节点信息
    @Data
    static class TreeRoot{
        private String treeRootNodeId;    //规则树根节点ID
        private String treeName;        //规则树名称
    }

    //规则树节点信息
    @Data
    static class TreeNode{
        private String treeNodeId;   //树节点ID J00 父节点
        /**
         * @see NodeType
         */
        private Integer nodeType;  //节点类型：1-子叶、2-果实
        private Integer nodeValue;  //节点值 nodeType=2：果实值
        private String ruleKey;    //规则key
        private String ruleDesc;   //规则描述
        private List<TreeNodeLink> treeNodeLinkList;    //节点链路

        @Getter
        @AllArgsConstructor
        public enum NodeType{
            LEAF(1),
            FRUIT(2)
            ;
            private Integer type;
        }

        private static TreeNode leftNode(String treeNodeId, String ruleKey, List<TreeNodeLink> treeNodeLinkList){
            TreeNode leafNode = new TreeNode();
            leafNode.setTreeNodeId(treeNodeId);
            leafNode.setNodeType(TreeNode.NodeType.LEAF.getType());
            leafNode.setRuleKey(ruleKey);
            leafNode.setTreeNodeLinkList(treeNodeLinkList);
            return leafNode;
        }

        public static TreeNode leftNode(String treeNodeId, String ruleKey){
            return leftNode(treeNodeId, ruleKey, null);
        }

        public static TreeNode fruitNode(String treeNodeId, String ruleKey, Integer nodeValue){
            TreeNode fruitNode = new TreeNode();
            fruitNode.setTreeNodeId(treeNodeId);
            fruitNode.setNodeType(TreeNode.NodeType.FRUIT.getType());
            fruitNode.setRuleKey(ruleKey);
            fruitNode.setNodeValue(nodeValue);
            return fruitNode;
        }

        public static TreeNode treeNode(Map<String, TreeNode> treeNodeMap, TreeNode ownNode,
                                        TreeNodeLink leftLink, TreeNodeLink rightLink,
                                        TreeNode leftNode, TreeNode rightNode){
            Assert.isTrue(ownNode != null, "节点不为空");
            treeNodeMap.put(ownNode.getTreeNodeId(), ownNode);
            //若是果实，维护左右链接 (一个链接 -> 果实节点)
            if(ownNode.getNodeType() == NodeType.FRUIT.getType()){
                Assert.isFalse(leftLink == null && rightLink == null, "果实节点，左右链接不能为空");
                Assert.isFalse(leftLink != null && rightLink != null, "果实节点，只能对应一个节点");
                if(leftLink != null){
                    leftLink.setNodeIdTo(ownNode.getTreeNodeId());
                }
                if(rightLink != null){
                    rightLink.setNodeIdTo(ownNode.getTreeNodeId());
                }
                return ownNode;
            }
            //若是叶节点，维护对应的左右链接 (叶节点 -> 左右链接)
            List<TreeNodeLink> links = new ArrayList<>();
            if(leftLink != null){
                Assert.isTrue(leftNode != null, "左节点不为空");
                leftLink.setNodeIdFrom(ownNode.getTreeNodeId());
                leftLink.setNodeIdTo(leftNode.getTreeNodeId());
                links.add(leftLink);
                treeNodeMap.put(leftNode.getTreeNodeId(), leftNode);
            }
            if(rightLink != null){
                Assert.isTrue(rightNode != null, "右节点不为空");
                rightLink.setNodeIdFrom(ownNode.getTreeNodeId());
                rightLink.setNodeIdTo(rightNode.getTreeNodeId());
                links.add(rightLink);
                treeNodeMap.put(rightNode.getTreeNodeId(), rightNode);
            }
            if(!CollectionUtils.isEmpty(links)){
                ownNode.setTreeNodeLinkList(links);
            }
            return ownNode;
        }

    }

    //规则树-连线信息
    @Data
    static class TreeNodeLink{
        private String nodeIdFrom;        //节点from
        private String nodeIdTo;          //节点to
        /**
         * @see Operator
         */
        private Integer ruleLimitType;  //限定类型 1:=;2:>;3:<;4:>=;5<=;
        private Integer ruleLimitValue;  //限定值

        @Getter
        @AllArgsConstructor
        public enum Operator{
            NOT_EQ(0, "!="),
            EQ(1, "="),
            GE(2, ">"),
            LE(3, "<"),
            GE_EQ(4, ">="),
            LE_EQ(5, "<="),
            ;
            private Integer type;
            private String code;

            public static Operator getByType(Integer type){
                if(type == null){
                    return null;
                }
                for (Operator operator : Operator.values()) {
                    if(Objects.equals(type, operator.getType())){
                        return operator;
                    }
                }
                return null;
            }
        }

        private static TreeNodeLink nodeLink(String preNodeId, String nextNodeId, Integer ruleLimitType, Integer ruleLimitValue){
            TreeNodeLink nodeLink = new TreeNodeLink();
            nodeLink.setNodeIdFrom(preNodeId);
            nodeLink.setRuleLimitType(ruleLimitType);
            nodeLink.setRuleLimitValue(ruleLimitValue);
            nodeLink.setNodeIdTo(nextNodeId);
            return nodeLink;
        }

        private static TreeNodeLink nodeLink(String preNodeId, Integer ruleLimitType, Integer ruleLimitValue){
            return nodeLink(preNodeId, null, ruleLimitType, ruleLimitValue);
        }

        public static TreeNodeLink nodeLink(Integer ruleLimitType, Integer ruleLimitValue){
            return nodeLink(null, null, ruleLimitType, ruleLimitValue);
        }

    }

    /********************规则树逻辑处理规则构建********************/
    //逻辑决策-接口定义
    interface LogicFilter{
        /**
         * 逻辑决策器
         * @param matterValue   决策值
         * @param linkList      决策节点
         * @return              下一个节点ID
         */
        String filter(Integer matterValue, List<TreeNodeLink> linkList);

        /**
         * 获取决策果实
         * @param decisionMatter    决策物料
         * @return                  决策果实
         */
        Integer matterValue(Map<String, Object> decisionMatter);
    }

    //基础逻辑处理器-模版方法
    abstract static class BaseLogic implements LogicFilter{
        @Override
        public String filter(Integer matterValue, List<TreeNodeLink> linkList) {
            for (TreeNodeLink nodeLink : linkList) {
                if(decisionLogic(matterValue, nodeLink)){
                    return nodeLink.getNodeIdTo();
                }
            }
            return null;
        }

        @Override
        public abstract Integer matterValue(Map<String, Object> decisionMatter);

        //决策逻辑 - 模版方法
        private boolean decisionLogic(Integer matterValue, TreeNodeLink nodeLink){
            switch (TreeNodeLink.Operator.getByType(nodeLink.getRuleLimitType())){
                case NOT_EQ:
                    return !Objects.equals(matterValue, nodeLink.getRuleLimitValue());
                case EQ:
                    return Objects.equals(matterValue, nodeLink.getRuleLimitValue());
                case GE:
                    return new BigDecimal(matterValue).compareTo(new BigDecimal(nodeLink.getRuleLimitValue())) > 0;
                case LE:
                    return new BigDecimal(matterValue).compareTo(new BigDecimal(nodeLink.getRuleLimitValue())) < 0;
                case GE_EQ:
                    return new BigDecimal(matterValue).compareTo(new BigDecimal(nodeLink.getRuleLimitValue())) >= 0;
                case LE_EQ:
                    return new BigDecimal(matterValue).compareTo(new BigDecimal(nodeLink.getRuleLimitValue())) <= 0;
                default:
                    throw new RuntimeException("无效的参数规则");
            }
        }
    }

    static class ItemCommentImagesFilter extends BaseLogic{
        @Override
        public Integer matterValue(Map<String, Object> decisionMatter) {
            return Integer.valueOf(decisionMatter.get("images").toString());
        }
    }

    static class ItemCommentVideosFilter extends BaseLogic{
        @Override
        public Integer matterValue(Map<String, Object> decisionMatter) {
            return Integer.valueOf(decisionMatter.get("videos").toString());
        }
    }

    static class ItemCommentStarFilter extends BaseLogic{
        @Override
        public Integer matterValue(Map<String, Object> decisionMatter) {
            return Integer.valueOf(decisionMatter.get("star").toString());
        }
    }

    static class ItemCommentTimeIntervalFilter extends BaseLogic{
        @Override
        public Integer matterValue(Map<String, Object> decisionMatter) {
            return Integer.valueOf(decisionMatter.get("time_interval").toString());
        }
    }

    static class ItemCommentTextFilter extends BaseLogic{
        @Override
        public Integer matterValue(Map<String, Object> decisionMatter) {
            return Integer.valueOf(decisionMatter.get("text").toString());
        }
    }

    /********************规则树业务逻辑处理********************/

    //决策树配置
    static class EngineConfig{
        public static Map<String, LogicFilter> LOGIC_FILTER_MAP;
        {
            LOGIC_FILTER_MAP = new ConcurrentHashMap<>();
            LOGIC_FILTER_MAP.put(ItemCommentImagesFilter.class.getName(), new ItemCommentImagesFilter());
            LOGIC_FILTER_MAP.put(ItemCommentVideosFilter.class.getName(), new ItemCommentVideosFilter());
            LOGIC_FILTER_MAP.put(ItemCommentTextFilter.class.getName(), new ItemCommentTextFilter());
            LOGIC_FILTER_MAP.put(ItemCommentStarFilter.class.getName(), new ItemCommentStarFilter());
            LOGIC_FILTER_MAP.put(ItemCommentTimeIntervalFilter.class.getName(), new ItemCommentTimeIntervalFilter());
        }
    }

    //决策
    interface IEngine{
        /**
         * 决策树逻辑执行引擎
         * @param decisionMatter    //决策物料
         * @return
         */
        EngineResult process(Map<String, Object> decisionMatter) throws Exception;
    }

    //执行抽象-模版方法
    @Slf4j
    abstract static class EngineBase extends EngineConfig implements IEngine{

        public abstract EngineResult process(Map<String, Object> decisionMatter) throws Exception;

        //模版方法
        protected TreeNode engineDecisionMaker(TreeRich treeRich, Map<String, Object> decisionMatter) throws Exception {
            TreeRoot treeRoot = treeRich.getTreeRoot();
            Map<String, TreeNode> treeNodeMap = treeRich.getTreeNodeMap();
            //从规则树根节点开始遍历
            TreeNode treeNodeInfo = treeNodeMap.get(treeRoot.getTreeRootNodeId());
            //节点类型[NodeType]；1子叶、2果实
            while (treeNodeInfo.getNodeType() == TreeNode.NodeType.LEAF.getType()){
                String ruleKey = treeNodeInfo.getRuleKey();
                LogicFilter logicFilter = LOGIC_FILTER_MAP.get(ruleKey);
                Integer matterValue = logicFilter.matterValue(decisionMatter);
                String nextNodeId = logicFilter.filter(matterValue, treeNodeInfo.getTreeNodeLinkList());
                treeNodeInfo = treeNodeMap.get(nextNodeId);
                if(treeNodeInfo == null){
                    log.info("决策树引擎=>null");
                    break;
                }
                log.info("决策树引擎=>{} treeNode：{} ruleKey：{} matterValue：{}", treeRoot.getTreeName(), treeNodeInfo.getTreeNodeId(), ruleKey, matterValue);
            }
            return treeNodeInfo;
        }

    }

    /**
     * 规则树-控制器
     */
    static class TreeEngineHandle extends EngineBase{
        //决策树
        private Class<? extends TreeRichBuilder> treeRichClass;
        private String data;

        public TreeEngineHandle(Class<? extends TreeRichBuilder> treeRichClass) {
            this.treeRichClass = treeRichClass;
        }

        public TreeEngineHandle(String data) {
            this.data = data;
        }

        @Override
        public EngineResult process(Map<String, Object> decisionMatter) throws Exception {
            TreeRich treeRich = null;
            if(data != null){
                treeRich = JSONObject.parseObject(data, TreeRich.class);

            }else {
                TreeRichBuilder treeRichBuilder = JDKProxyFactory.getProxy(treeRichClass);
                treeRich = treeRichBuilder.initTreeRich();
            }
            TreeNode treeNode = engineDecisionMaker(treeRich, decisionMatter);
            return EngineResult.builder()
                    .nodeId(treeNode.getTreeNodeId())
                    .nodeValue(treeNode.getNodeValue())
                    .build();
        }
        public EngineResult process(String data, Map<String, Object> decisionMatter) throws Exception {
            TreeRich treeRich = JSONObject.parseObject(data, TreeRich.class);
            TreeNode treeNode = engineDecisionMaker(treeRich, decisionMatter);
            return EngineResult.builder()
                    .nodeId(treeNode.getTreeNodeId())
                    .nodeValue(treeNode.getNodeValue())
                    .build();
        }

    }

    /********************工厂模式构建不同的决策树模型(数据初始化)********************/

    //决策树构建
    interface TreeRichBuilder{
        TreeRich initTreeRich();
    }

    static class ItemCommentImagesTreeRich implements TreeRichBuilder{
        public ItemCommentImagesTreeRich(){}

//        @Override
//        public TreeRich initTreeRich_01() {
//            // 节点J01：根节点
//            TreeNode leafNode_01 = new TreeNode();
//            leafNode_01.setTreeNodeId("J01");
//            leafNode_01.setNodeType(TreeNode.NodeType.LEAF.getType());
//            leafNode_01.setRuleKey(ItemCommentImagesFilter.class.getName());
//            // 链接L01：J01->L01->J02
//            TreeNodeLink nodeLink_01 = new TreeNodeLink();
//            nodeLink_01.setNodeIdFrom(leafNode_01.getTreeNodeId());
//            nodeLink_01.setRuleLimitType(TreeNodeLink.Operator.LE_EQ.getType());
//            nodeLink_01.setRuleLimitValue(0);
//            // 链接L02：J01->L02
//            TreeNodeLink nodeLink_02 = new TreeNodeLink();
//            nodeLink_02.setNodeIdFrom(leafNode_01.getTreeNodeId());
//            nodeLink_02.setRuleLimitType(TreeNodeLink.Operator.GE.getType());
//            nodeLink_02.setRuleLimitValue(0);
//            // 果实G01：L01->G01
//            TreeNode fruitNode_01 = new TreeNode();
//            fruitNode_01.setTreeNodeId("G01");
//            fruitNode_01.setNodeType(TreeNode.NodeType.FRUIT.getType());
//            fruitNode_01.setNodeValue(0);
//            fruitNode_01.setRuleKey(ItemCommentImagesFilter.class.getName());
//            nodeLink_01.setNodeIdTo(fruitNode_01.getTreeNodeId());
//            // 节点J02：L02->J02
//            TreeNode leafNode_02 = new TreeNode();
//            leafNode_02.setTreeNodeId("J02");
//            leafNode_02.setNodeType(TreeNode.NodeType.LEAF.getType());
//            leafNode_02.setRuleKey(ItemCommentImagesFilter.class.getName());
//            nodeLink_02.setNodeIdTo(leafNode_02.getTreeNodeId());
//            //节点J01 链接维护 J01->L01 J02->L02
//            List<TreeNodeLink> treeNodeLinkList_01 = new ArrayList<>();
//            treeNodeLinkList_01.add(nodeLink_01);
//            treeNodeLinkList_01.add(nodeLink_02);
//            leafNode_01.setTreeNodeLinkList(treeNodeLinkList_01);
//
//            // 链接L03：J02->L03
//            TreeNodeLink nodeLink_03 = new TreeNodeLink();
//            nodeLink_03.setNodeIdFrom(leafNode_02.getTreeNodeId());
//            nodeLink_03.setRuleLimitType(TreeNodeLink.Operator.EQ.getType());
//            nodeLink_03.setRuleLimitValue(1);
//            // 链接L04：J02->L04
//            TreeNodeLink nodeLink_04 = new TreeNodeLink();
//            nodeLink_04.setNodeIdFrom(leafNode_02.getTreeNodeId());
//            nodeLink_04.setRuleLimitType(TreeNodeLink.Operator.GE.getType());
//            nodeLink_04.setRuleLimitValue(1);
//            //果实G02：L03->G02
//            TreeNode fruitNode_02 = new TreeNode();
//            fruitNode_02.setTreeNodeId("G03");
//            fruitNode_02.setNodeType(TreeNode.NodeType.FRUIT.getType());
//            fruitNode_02.setNodeValue(10);
//            fruitNode_02.setRuleKey(ItemCommentImagesFilter.class.getName());
//            nodeLink_03.setNodeIdTo(fruitNode_02.getTreeNodeId());
//            //节点03：L03->J03
//            TreeNode leafNode_03 = new TreeNode();
//            leafNode_03.setTreeNodeId("J03");
//            leafNode_03.setNodeType(TreeNode.NodeType.LEAF.getType());
//            leafNode_03.setRuleKey(ItemCommentImagesFilter.class.getName());
//            nodeLink_04.setNodeIdTo(leafNode_03.getTreeNodeId());
//            //节点J02 链接维护 J02->L03 J02->L04
//            List<TreeNodeLink> treeNodeLinkList_02 = new ArrayList<>();
//            treeNodeLinkList_02.add(nodeLink_03);
//            treeNodeLinkList_02.add(nodeLink_04);
//            leafNode_02.setTreeNodeLinkList(treeNodeLinkList_02);
//
//            // 链接L05：J03->L05
//            TreeNodeLink nodeLink_05 = new TreeNodeLink();
//            nodeLink_05.setNodeIdFrom(leafNode_03.getTreeNodeId());
//            nodeLink_05.setRuleLimitType(TreeNodeLink.Operator.LE_EQ.getType());
//            nodeLink_05.setRuleLimitValue(4);
//            // 链接L06：J02->L04
//            TreeNodeLink nodeLink_06 = new TreeNodeLink();
//            nodeLink_06.setNodeIdFrom(leafNode_03.getTreeNodeId());
//            nodeLink_06.setRuleLimitType(TreeNodeLink.Operator.GE.getType());
//            nodeLink_06.setRuleLimitValue(4);
//            //果实G03：L05->G03
//            TreeNode fruitNode_03 = new TreeNode();
//            fruitNode_03.setTreeNodeId("G03");
//            fruitNode_03.setNodeType(TreeNode.NodeType.FRUIT.getType());
//            fruitNode_03.setNodeValue(14);
//            fruitNode_03.setRuleKey(ItemCommentImagesFilter.class.getName());
//            nodeLink_05.setNodeIdTo(fruitNode_03.getTreeNodeId());
//            //节点04：L04->J04
//            TreeNode leafNode_04 = new TreeNode();
//            leafNode_04.setTreeNodeId("J04");
//            leafNode_04.setNodeType(TreeNode.NodeType.LEAF.getType());
//            leafNode_04.setRuleKey(ItemCommentImagesFilter.class.getName());
//            nodeLink_06.setNodeIdTo(leafNode_04.getTreeNodeId());
//            //节点J03 链接维护 J03->L05 J03->L06
//            List<TreeNodeLink> treeNodeLinkList_03 = new ArrayList<>();
//            treeNodeLinkList_03.add(nodeLink_05);
//            treeNodeLinkList_03.add(nodeLink_06);
//            leafNode_03.setTreeNodeLinkList(treeNodeLinkList_03);
//
//            // 链接L07：J04->L07
//            TreeNodeLink nodeLink_07 = new TreeNodeLink();
//            nodeLink_07.setNodeIdFrom(leafNode_04.getTreeNodeId());
//            nodeLink_07.setRuleLimitType(TreeNodeLink.Operator.LE_EQ.getType());
//            nodeLink_07.setRuleLimitValue(6);
//            // 链接L08：J04->L08
//            TreeNodeLink nodeLink_08 = new TreeNodeLink();
//            nodeLink_08.setNodeIdFrom(leafNode_04.getTreeNodeId());
//            nodeLink_08.setRuleLimitType(TreeNodeLink.Operator.GE.getType());
//            nodeLink_08.setRuleLimitValue(6);
//            //果实G04：L07->G04
//            TreeNode fruitNode_04 = new TreeNode();
//            fruitNode_04.setTreeNodeId("G04");
//            fruitNode_04.setNodeType(TreeNode.NodeType.FRUIT.getType());
//            fruitNode_04.setNodeValue(19);
//            fruitNode_04.setRuleKey(ItemCommentImagesFilter.class.getName());
//            nodeLink_07.setNodeIdTo(fruitNode_04.getTreeNodeId());
//            //节点05：L08->J05
//            TreeNode leafNode_05 = new TreeNode();
//            leafNode_05.setTreeNodeId("J05");
//            leafNode_05.setNodeType(TreeNode.NodeType.LEAF.getType());
//            leafNode_05.setRuleKey(ItemCommentImagesFilter.class.getName());
//            nodeLink_08.setNodeIdTo(leafNode_05.getTreeNodeId());
//            //节点J04 链接维护 J03->L07 J03->L08
//            List<TreeNodeLink> treeNodeLinkList_04 = new ArrayList<>();
//            treeNodeLinkList_04.add(nodeLink_07);
//            treeNodeLinkList_04.add(nodeLink_08);
//            leafNode_04.setTreeNodeLinkList(treeNodeLinkList_04);
//
//            // 链接L09：J05->L09
//            TreeNodeLink nodeLink_09 = new TreeNodeLink();
//            nodeLink_09.setNodeIdFrom(leafNode_05.getTreeNodeId());
//            nodeLink_09.setRuleLimitType(TreeNodeLink.Operator.LE_EQ.getType());
//            nodeLink_09.setRuleLimitValue(8);
//            // 链接L08：J04->L08
//            TreeNodeLink nodeLink_10 = new TreeNodeLink();
//            nodeLink_10.setNodeIdFrom(leafNode_05.getTreeNodeId());
//            nodeLink_10.setRuleLimitType(TreeNodeLink.Operator.GE.getType());
//            nodeLink_10.setRuleLimitValue(8);
//            //果实G05：L09->G05
//            TreeNode fruitNode_05 = new TreeNode();
//            fruitNode_05.setTreeNodeId("G05");
//            fruitNode_05.setNodeType(TreeNode.NodeType.FRUIT.getType());
//            fruitNode_05.setNodeValue(22);
//            fruitNode_05.setRuleKey(ItemCommentImagesFilter.class.getName());
//            nodeLink_09.setNodeIdTo(fruitNode_05.getTreeNodeId());
//            //果实G06：L10->G06
//            TreeNode fruitNode_06 = new TreeNode();
//            fruitNode_06.setTreeNodeId("G06");
//            fruitNode_06.setNodeType(TreeNode.NodeType.FRUIT.getType());
//            fruitNode_06.setNodeValue(22);
//            fruitNode_06.setRuleKey(ItemCommentImagesFilter.class.getName());
//            nodeLink_10.setNodeIdTo(fruitNode_06.getTreeNodeId());
//            //节点J04 链接维护 J04->L09 J04->L10
//            List<TreeNodeLink> treeNodeLinkList_05 = new ArrayList<>();
//            treeNodeLinkList_05.add(nodeLink_09);
//            treeNodeLinkList_05.add(nodeLink_10);
//            leafNode_04.setTreeNodeLinkList(treeNodeLinkList_05);
//
//            // 树根
//            TreeRoot treeRoot = new TreeRoot();
//            treeRoot.setTreeId("000");
//            treeRoot.setTreeRootNodeId("J01");
//            treeRoot.setTreeName("规则决策树");
//
//            Map<String, TreeNode> treeNodeMap = new HashMap<>();
//            treeNodeMap.put("J01", leafNode_01);
//            treeNodeMap.put("J02", leafNode_02);
//            treeNodeMap.put("J03", leafNode_03);
//            treeNodeMap.put("J04", leafNode_04);
//            treeNodeMap.put("J05", leafNode_05);
//            treeNodeMap.put("G01", fruitNode_01);
//            treeNodeMap.put("G02", fruitNode_02);
//            treeNodeMap.put("G03", fruitNode_03);
//            treeNodeMap.put("G04", fruitNode_04);
//            treeNodeMap.put("G05", fruitNode_05);
//            treeNodeMap.put("G06", fruitNode_06);
//
//            TreeRich treeRich = new TreeRich();
//            treeRich.setTreeRoot(treeRoot);
//            treeRich.setTreeNodeMap(treeNodeMap);
//            return treeRich;
//        }

//        @Override
//        public TreeRich initTreeRich() {
//            //与initTreeRich01等价
//            Map<String, TreeNode> treeNodeMap = new HashMap<>();
//            TreeNode node01 = TreeNode.treeNode(treeNodeMap,
//                    TreeNode.leftNode("J01", ItemCommentImagesFilter.class.getName()),
//                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.LE_EQ.getType(), 0),
//                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.GE.getType(), 0),
//                    TreeNode.fruitNode("G01", ItemCommentImagesFilter.class.getName(), 0),
//                    TreeNode.leftNode("J02", ItemCommentImagesFilter.class.getName()));
//            TreeNode node02 = TreeNode.treeNode(treeNodeMap, treeNodeMap.get("J02"),
//                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.EQ.getType(), 1),
//                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.GE.getType(), 1),
//                    TreeNode.fruitNode("G02", ItemCommentImagesFilter.class.getName(), 10),
//                    TreeNode.leftNode("J03", ItemCommentImagesFilter.class.getName()));
//            TreeNode node03 = TreeNode.treeNode(treeNodeMap, treeNodeMap.get("J03"),
//                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.LE_EQ.getType(), 4),
//                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.GE.getType(), 4),
//                    TreeNode.fruitNode("G03", ItemCommentImagesFilter.class.getName(), 14),
//                    TreeNode.leftNode("J04", ItemCommentImagesFilter.class.getName()));
//            TreeNode node04 = TreeNode.treeNode(treeNodeMap, treeNodeMap.get("J04"),
//                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.LE_EQ.getType(), 6),
//                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.GE.getType(), 6),
//                    TreeNode.fruitNode("G04", ItemCommentImagesFilter.class.getName(), 19),
//                    TreeNode.leftNode("J05", ItemCommentImagesFilter.class.getName()));
//            TreeNode node05 = TreeNode.treeNode(treeNodeMap, treeNodeMap.get("J05"),
//                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.LE_EQ.getType(), 8),
//                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.GE.getType(), 8),
//                    TreeNode.fruitNode("G05", ItemCommentImagesFilter.class.getName(), 22),
//                    TreeNode.fruitNode("G06", ItemCommentImagesFilter.class.getName(), 22));
//            // 树根
//            TreeRoot treeRoot = new TreeRoot();
//            treeRoot.setTreeId("000");
//            treeRoot.setTreeRootNodeId("J01");
//            treeRoot.setTreeName("规则决策树");
//            TreeRich treeRich = new TreeRich();
//            treeRich.setTreeRoot(treeRoot);
//            treeRich.setTreeNodeMap(treeNodeMap);
//            return treeRich;
//        }
        @Override
        public TreeRich initTreeRich() {
            //与initTreeRich01等价
            Map<String, TreeNode> treeNodeMap = new HashMap<>();
            TreeNode node01 = TreeNode.treeNode(treeNodeMap,
                    TreeNode.leftNode("J01", ItemCommentImagesFilter.class.getName()),
                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.LE_EQ.getType(), 0),
                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.GE.getType(), 0),
                    TreeNode.fruitNode("G01", ItemCommentImagesFilter.class.getName(), 0),
                    TreeNode.leftNode("J02", ItemCommentImagesFilter.class.getName()));
            TreeNode node02 = TreeNode.treeNode(treeNodeMap, treeNodeMap.get("J02"),
                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.EQ.getType(), 1),
                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.GE.getType(), 1),
                    TreeNode.fruitNode("G02", ItemCommentImagesFilter.class.getName(), 10),
                    TreeNode.leftNode("J03", ItemCommentImagesFilter.class.getName()));
            TreeNode node03 = TreeNode.treeNode(treeNodeMap, treeNodeMap.get("J03"),
                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.LE_EQ.getType(), 4),
                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.GE.getType(), 4),
                    TreeNode.leftNode("JJ3", ItemCommentImagesFilter.class.getName()),
                    TreeNode.leftNode("J04", ItemCommentImagesFilter.class.getName()));

            TreeNode.treeNode(treeNodeMap, treeNodeMap.get("JJ3"),
                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.LE_EQ.getType(), 3),
                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.GE.getType(), 3),
                    TreeNode.fruitNode("GJ3", ItemCommentImagesFilter.class.getName(), 11),
                    TreeNode.fruitNode("GJ4", ItemCommentImagesFilter.class.getName(), 13));

            TreeNode node04 = TreeNode.treeNode(treeNodeMap, treeNodeMap.get("J04"),
                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.LE_EQ.getType(), 6),
                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.GE.getType(), 6),
                    TreeNode.fruitNode("G04", ItemCommentImagesFilter.class.getName(), 19),
                    TreeNode.leftNode("J05", ItemCommentImagesFilter.class.getName()));
            TreeNode node05 = TreeNode.treeNode(treeNodeMap, treeNodeMap.get("J05"),
                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.LE_EQ.getType(), 8),
                    TreeNodeLink.nodeLink(TreeNodeLink.Operator.GE.getType(), 8),
                    TreeNode.fruitNode("G05", ItemCommentImagesFilter.class.getName(), 22),
                    TreeNode.fruitNode("G06", ItemCommentImagesFilter.class.getName(), 22));
            // 树根
            TreeRoot treeRoot = new TreeRoot();
            treeRoot.setTreeRootNodeId("J01");
            treeRoot.setTreeName("图片规则决策树");
            TreeRich treeRich = new TreeRich();
            treeRich.setTreeRoot(treeRoot);
            treeRich.setTreeNodeMap(treeNodeMap);
            System.out.println(JSON.toJSONString(treeRich));
            return treeRich;
        }

    }

    static class ItemCommentTextTreeRich implements TreeRichBuilder{
        public ItemCommentTextTreeRich(){}
        @Override
        public TreeRich initTreeRich() {
            // 树根
            TreeRoot treeRoot = new TreeRoot();
            treeRoot.setTreeRootNodeId("J01");
            treeRoot.setTreeName("图片规则决策树");
            TreeRich treeRich = new TreeRich();
            treeRich.setTreeRoot(treeRoot);
            return treeRich;
        }
    }

    //工厂代理类
    static class JDKProxyFactory {
        public static <T> T getProxy(Class<? extends T> aClass) throws Exception {
//            JDKInvocationHandler handler = new JDKInvocationHandler(aClass.newInstance());
            //jdk动态代理
            InvocationHandler handler = (proxy, method, args) -> {
                return method.invoke(aClass.getConstructor().newInstance(), args);
            };
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            Class<?>[] classes = aClass.getInterfaces();
            return (T) Proxy.newProxyInstance(classLoader, new Class[]{classes[0]}, handler);
        }
    }


    //jdk动态代理
    static class JDKInvocationHandler implements InvocationHandler {
        private Object obj;
        public JDKInvocationHandler(Object obj){
            this.obj = obj;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return method.invoke(obj, args);
        }
    }

    //工具类
    static class ClassLoaderUtils {
        public static Class<?>[] getClazzByArgs(Object[] args) {
            Class<?>[] parameterTypes = new Class[args.length];
            for (int i = 0; i < args.length; i++) {
                if (args[i] instanceof ArrayList) {
                    parameterTypes[i] = List.class;
                    continue;
                }
                if (args[i] instanceof LinkedList) {
                    parameterTypes[i] = List.class;
                    continue;
                }
                if (args[i] instanceof HashMap) {
                    parameterTypes[i] = Map.class;
                    continue;
                }
                if (args[i] instanceof Long){
                    parameterTypes[i] = long.class;
                    continue;
                }
                if (args[i] instanceof Double){
                    parameterTypes[i] = double.class;
                    continue;
                }
                if (args[i] instanceof TimeUnit){
                    parameterTypes[i] = TimeUnit.class;
                    continue;
                }
                parameterTypes[i] = args[i].getClass();
            }
            return parameterTypes;
        }
    }

    /********************测试********************/

    @Test
    public void test01() throws Exception {
        Map<String, Object> decisionMatter = new HashMap<>();
        decisionMatter.put("images", 3);
        decisionMatter.put("videos", 1);
        decisionMatter.put("text", "asdasdasdasdsadasdasdasdasd".length());
        decisionMatter.put("star", 3);
        decisionMatter.put("time_interval", 3);


//        EngineResult images = new TreeEngineHandle(ItemCommentImagesTreeRich.class).process(decisionMatter);
//        EngineResult videos = new TreeEngineHandle(ItemCommentVideosTreeRich.class).process(decisionMatter);
//        EngineResult text = new TreeEngineHandle(ItemCommentImagesTreeRich.class).process(decisionMatter);
//        EngineResult star = new TreeEngineHandle(ItemCommentImagesTreeRich.class).process(decisionMatter);
//        EngineResult timeInterval = new TreeEngineHandle(ItemCommentImagesTreeRich.class).process(decisionMatter);

        String data = "{\"treeNodeMap\":{\"G02\":{\"nodeType\":2,\"nodeValue\":10,\"ruleKey\":\"design.pattern.Lu15CompositePattern.CompositePattern06$ItemCommentImagesFilter\",\"treeNodeId\":\"G02\"},\"G01\":{\"nodeType\":2,\"nodeValue\":0,\"ruleKey\":\"design.pattern.Lu15CompositePattern.CompositePattern06$ItemCommentImagesFilter\",\"treeNodeId\":\"G01\"},\"J01\":{\"nodeType\":1,\"ruleKey\":\"design.pattern.Lu15CompositePattern.CompositePattern06$ItemCommentImagesFilter\",\"treeNodeId\":\"J01\",\"treeNodeLinkList\":[{\"nodeIdFrom\":\"J01\",\"nodeIdTo\":\"G01\",\"ruleLimitType\":5,\"ruleLimitValue\":0},{\"nodeIdFrom\":\"J01\",\"nodeIdTo\":\"J02\",\"ruleLimitType\":2,\"ruleLimitValue\":0}]},\"G04\":{\"nodeType\":2,\"nodeValue\":19,\"ruleKey\":\"design.pattern.Lu15CompositePattern.CompositePattern06$ItemCommentImagesFilter\",\"treeNodeId\":\"G04\"},\"J03\":{\"nodeType\":1,\"ruleKey\":\"design.pattern.Lu15CompositePattern.CompositePattern06$ItemCommentImagesFilter\",\"treeNodeId\":\"J03\",\"treeNodeLinkList\":[{\"nodeIdFrom\":\"J03\",\"nodeIdTo\":\"JJ3\",\"ruleLimitType\":5,\"ruleLimitValue\":4},{\"nodeIdFrom\":\"J03\",\"nodeIdTo\":\"J04\",\"ruleLimitType\":2,\"ruleLimitValue\":4}]},\"G06\":{\"nodeType\":2,\"nodeValue\":22,\"ruleKey\":\"design.pattern.Lu15CompositePattern.CompositePattern06$ItemCommentImagesFilter\",\"treeNodeId\":\"G06\"},\"J02\":{\"nodeType\":1,\"ruleKey\":\"design.pattern.Lu15CompositePattern.CompositePattern06$ItemCommentImagesFilter\",\"treeNodeId\":\"J02\",\"treeNodeLinkList\":[{\"nodeIdFrom\":\"J02\",\"nodeIdTo\":\"G02\",\"ruleLimitType\":1,\"ruleLimitValue\":1},{\"nodeIdFrom\":\"J02\",\"nodeIdTo\":\"J03\",\"ruleLimitType\":2,\"ruleLimitValue\":1}]},\"G05\":{\"nodeType\":2,\"nodeValue\":22,\"ruleKey\":\"design.pattern.Lu15CompositePattern.CompositePattern06$ItemCommentImagesFilter\",\"treeNodeId\":\"G05\"},\"J05\":{\"nodeType\":1,\"ruleKey\":\"design.pattern.Lu15CompositePattern.CompositePattern06$ItemCommentImagesFilter\",\"treeNodeId\":\"J05\",\"treeNodeLinkList\":[{\"nodeIdFrom\":\"J05\",\"nodeIdTo\":\"G05\",\"ruleLimitType\":5,\"ruleLimitValue\":8},{\"nodeIdFrom\":\"J05\",\"nodeIdTo\":\"G06\",\"ruleLimitType\":2,\"ruleLimitValue\":8}]},\"J04\":{\"nodeType\":1,\"ruleKey\":\"design.pattern.Lu15CompositePattern.CompositePattern06$ItemCommentImagesFilter\",\"treeNodeId\":\"J04\",\"treeNodeLinkList\":[{\"nodeIdFrom\":\"J04\",\"nodeIdTo\":\"G04\",\"ruleLimitType\":5,\"ruleLimitValue\":6},{\"nodeIdFrom\":\"J04\",\"nodeIdTo\":\"J05\",\"ruleLimitType\":2,\"ruleLimitValue\":6}]},\"GJ4\":{\"nodeType\":2,\"nodeValue\":13,\"ruleKey\":\"design.pattern.Lu15CompositePattern.CompositePattern06$ItemCommentImagesFilter\",\"treeNodeId\":\"GJ4\"},\"GJ3\":{\"nodeType\":2,\"nodeValue\":11,\"ruleKey\":\"design.pattern.Lu15CompositePattern.CompositePattern06$ItemCommentImagesFilter\",\"treeNodeId\":\"GJ3\"},\"JJ3\":{\"nodeType\":1,\"ruleKey\":\"design.pattern.Lu15CompositePattern.CompositePattern06$ItemCommentImagesFilter\",\"treeNodeId\":\"JJ3\",\"treeNodeLinkList\":[{\"nodeIdFrom\":\"JJ3\",\"nodeIdTo\":\"GJ3\",\"ruleLimitType\":5,\"ruleLimitValue\":3},{\"nodeIdFrom\":\"JJ3\",\"nodeIdTo\":\"GJ4\",\"ruleLimitType\":2,\"ruleLimitValue\":3}]}},\"treeRoot\":{\"treeName\":\"图片规则决策树\",\"treeRootNodeId\":\"J01\"}}";
        EngineResult images = new TreeEngineHandle(data).process(decisionMatter);

        log.info("测试结果：{}", JSON.toJSONString(images));
    }

}
